﻿///
/// Authors: Lee Gary 
///
/// Date: 24/09/2010
///
/// Purpose: 
///
/// Naming conventions class for getting SharePoint friendly name while giving the 
/// programmer/users the flexibility to choose what to replace with
/// 
/// Future:
/// 1.) Consider using Microsoft.SharePoint.Utilities.SPUrlUtility 
/// 2.) Improve regex and logging method, it's too lame and inefficient now
/// 
using System;
using System.Text.RegularExpressions;
using GSPMigratorCore.Misc;

namespace GSPMigratorCore.NamingConventions
{
    public class GSPReplacer : BaseClass
    {
        public const int MAXFOLDERLENGTH = 128, MAXFILELENGTH = 123;
        public static int MAXURLLENGTH = 259;
        
        #region regular expressions

        private static Regex invalidCharsRegex =
            new Regex(@"[\*\?\|\\\t""'<>#{}%~&]", RegexOptions.Compiled);

        private static Regex invalidRulesRegex =
            new Regex(@"\.{2,}", RegexOptions.Compiled);

        private static Regex startEndRegex =
            new Regex(@"^[\. ]|[\. ]$", RegexOptions.Compiled);

        private static Regex extraSpacesRegex =
            new Regex(" {2,}", RegexOptions.Compiled);

        #endregion

        #region GetSharePointFriendlyName
        /// <summary>
        /// Returns a folder or file name that 
        /// conforms to SharePoint's naming restrictions
        /// </summary>
        /// <param name="original">
        /// The original file or folder name.  
        /// For files, this should be the file name without the extension. 
        /// </param>
        /// <param name="currentPathLength">
        /// The current folder's path length
        /// </param>
        /// <param name="maxItemLength">
        /// The maximum allowed number of characters for this file or folder.
        /// For a file, it will be MAXFILELENGTH.
        /// For a folder, it will be MAXFOLDERLENGTH.
        /// </param>
        public static string GetSharePointFriendlyName(string original
            , int currentPathLength, int maxItemLength, string replaceWith)
        {
            string friendlyName = CheckExtraSpaces(original, replaceWith);
            friendlyName = CheckInvalidChar(friendlyName, replaceWith);
            friendlyName = CheckInvalidRules(friendlyName, replaceWith);
            friendlyName = CheckStartEnd(friendlyName, replaceWith);

            // assign maximum item length
            int maxLength = (currentPathLength + maxItemLength > MAXURLLENGTH)
                ? MAXURLLENGTH - currentPathLength
                : maxItemLength;

            if (maxLength <= 0)
            {
                WriteLog(LogLevel.Error, "Exception10: Nested URL is too long");
                throw new ApplicationException("Current path is too long for importing into SharePoint");
            }
            // return exception if too long         
            if (friendlyName.Length > maxLength)
            {
                WriteLog(LogLevel.Error, "Exception7: " + original);
                throw new ApplicationException("Current path is too long for importing into SharePoint");
            }

            friendlyName = SharePointFolderReservedWordsHandler(friendlyName, replaceWith);
            if (!string.Equals(original, friendlyName, StringComparison.OrdinalIgnoreCase))
            {
                WriteLog(LogLevel.Info, "Info: Renamed: "+ original + " to: " + friendlyName);
            }
            return friendlyName;
        }

        internal static string SharePointFolderReservedWordsHandler(string original, string replaceWith)
        {
            string[] spReservedWords = {"images", ".com", ".files", "_files", "-Dateien", "_fichiers",
                                        "_bestanden", "_file", "_archivos", "-filer", "_tiedostot",
                                        "_pliki", "_soubory", "_elemei", "_ficheiros", "_arquivos",
                                        "_dosyalar", "_datoteke", "_fitxers", "_failid", "_fails",
                                        "_bylos", "_fajlovi", "_fitxategiak", ".soap" };

            foreach (string spReservedWord in spReservedWords)
            { 
                if(original.EndsWith(spReservedWord, StringComparison.OrdinalIgnoreCase))
                {
                    original = original + replaceWith;
                    WriteLog(LogLevel.Info, "Exception9: " + original);
                    break;
                }
            }
            return original;
        }

        internal static string CheckInvalidChar(string original, string replaceWith)
        {
            string friendlyName = invalidCharsRegex.Replace(original, replaceWith);
            
            if (!friendlyName.Equals(original))
            {
                WriteLog(LogLevel.Info, "Exception4: " + original);
            }
            return friendlyName;
        }

        internal static string CheckInvalidRules(string original, string replaceWith)
        {
            string friendlyName = invalidRulesRegex.Replace(original, replaceWith);

            if (!friendlyName.Equals(original))
            {
                WriteLog(LogLevel.Info, "Exception5: " + original);
            }
            return friendlyName;
        }

        internal static string CheckExtraSpaces(string original, string replaceWith)
        {
            string friendlyName = extraSpacesRegex.Replace(original, replaceWith);

            if (!friendlyName.Equals(original))
            {
                WriteLog(LogLevel.Info, "Exception6: " + original);
            }
            return friendlyName;
        }

        internal static string CheckStartEnd(string original, string replaceWith)
        {
            string friendlyName = startEndRegex.Replace(original, replaceWith);

            if (!friendlyName.Equals(original))
            {
                WriteLog(LogLevel.Info, "Exception8: " + original);
            }
            return friendlyName;
        }
        #endregion

        #region Parser

        public static string ExtractDocumentLibraryName(string input, string url)
        {
            input = input.Replace(url, string.Empty);
            input = input.Replace(@"\", "/");
            if(input.StartsWith("/"))
            {
                input = input.Substring(1);
            }
            int i = input.IndexOf("/");
            if (i != -1)
            {
                input = input.Substring(0, i);
            }
            return input;
        }

        public static string ExtractFolderTaxonomy(string input, string url)
        {
            input = input.Replace(url, string.Empty);
            input = input.Replace(@"\", "/");
            if (input.StartsWith("/"))
            {
                input = input.Substring(1);
            }
            return input;
        }

        public static string ExtractFolderTaxonomyWOFileName(string input, string url)
        {
            input = input.Replace(url, string.Empty);
            input = input.Replace(@"\", "/");
            if (input.StartsWith("/"))
            {
                input = input.Substring(1);
            }
            int i = input.LastIndexOf(@"/");
            input = input.Substring(0, i);
            return input;
        }

        //public static string ExtractFileName(string input)
        //{
        //    int i = input.LastIndexOf(@"\");
        //    return input.Substring(i);
        //}

        public static string ResolveHTTPUrl(string input)
        {
            input = input.Replace("/\\", "/");
            input = input.Replace("\\", "/");
            if (!input.StartsWith("http://") && !input.StartsWith("https://"))
            {           
                input = input.Replace("https:/", "https://");
                input = input.Replace("http:/", "http://");
            }
            return input;
        }

        public static string ReplaceDoubleSlashes(string input)
        {
            return input = input.Replace("\\", "/").Replace("//","/");
        }

        #endregion
    }
}
